/**
 * @author salim & sidyous
 *
 */

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ServerObject {

	/*
	 * Attributes
	 */

	// Core
	private int id;
	public Object obj;

	// Synchronization
	private Lock psy;
	private Lock psywriter;
	
	// Readers & writer
	private Client_itf writer;
	private ArrayList<Client_itf> readers;

	/*
	 * Methods
	 */

	public ServerObject(Object obj, int id) {
		super();
		System.out.println("ServerObject : ServerObject " + id);
		this.id = id;
		this.obj = obj;
		psy = new ReentrantLock();
		psywriter = new ReentrantLock();
		writer = null;
		readers = new ArrayList<Client_itf>();
	}

	public Object lock_read(Client_itf client) throws RemoteException {
		System.out.println("ServerObject : lock_read " + id);
	
		psy.lock();
		
		if (writer != null) {
			obj = writer.reduce_lock(id);
			readers.add(writer);
			writer = null;
		}
		readers.add(client);
		
		psy.unlock();
		
		return obj;
	}

	public Object lock_write(Client_itf client) throws RemoteException {
		System.out.println("ServerObject : lock_write " + id);
		
		//If another one asked for the writing lock, then return null
		if (!psywriter.tryLock()) {System.out.println("NNNNNNNNUUUUUUULLLLLLLLLLLLLLLLLL"); return null;}
		
		psy.lock();
		
		if (writer != null) {
			obj = writer.invalidate_writer(id);
			writer = null;
		} else {
			for (Client_itf c : readers) {
				if (!c.equals(client))
				{
					System.out.println(c);
					c.invalidate_reader(id);
				}
			}
		}
		readers = new ArrayList<Client_itf>();
		writer = client;
		
		psy.unlock();
		psywriter.unlock();
		
		return obj;
	}

}
